package com.wei.czz.common.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.handler.WriteHandler;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy;
import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy;
import com.wei.czz.common.enums.common.FileTypeEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.vo.common.UploadVo;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2024-06-28 11:59:50
 * className: ExcelUtils excel操作工具类
 * version: 1.0
 * description:
 */
public class ExcelUtils {

    private static final Logger log = LoggerFactory.getLogger(ExcelUtils.class);

    /**
     * easyexcel写文件操作
     * @param fileName  文件名称
     * @param dataList  数据列表
     * @param tClass    泛型类class对象
     * @param <T> 泛型类型
     */
    public static <T> void writeResponse(String fileName, List<T> dataList, Class<T> tClass,
                                         HttpServletResponse response) {
        writeResponse(fileName, fileName, dataList, null, tClass, basicWriteHandlerList(), response);
    }

    /**
     * easyexcel写文件操作
     * @param fileName  文件名称
     * @param dataList  数据列表
     * @param tClass    泛型类class对象
     * @param <T> 泛型类型
     */
    public static <T> void writeResponse(String fileName, String sheetName, List<T> dataList, Class<T> tClass,
                                         HttpServletResponse response) {
        writeResponse(fileName, sheetName, dataList, null, tClass, basicWriteHandlerList(), response);
    }

    /**
     * easyexcel写文件操作
     * @param fileName         文件名称
     * @param dataList         数据列表
     * @param writeHandlerList 数据列表
     * @param tClass           泛型类class对象
     * @param <T> 泛型类型
     */
    public static <T> void writeResponse(String fileName, List<T> dataList, Class<T> tClass,
                                         List<WriteHandler> writeHandlerList, HttpServletResponse response) {
        writeResponse(fileName, fileName, dataList, null, tClass, writeHandlerList, response);
    }

    /**
     * easyexcel写文件操作
     * @param fileName  文件名称
     * @param dataList  数据列表
     * @param headList  数据列表
     * @param tClass    泛型类class对象
     * @param response  http响应对象
     * @param <T> 泛型类型
     */
    public static <T> void writeResponse(String fileName, List<T> dataList, List<List<String>> headList,
                                         Class<T> tClass, HttpServletResponse response) {
        writeResponse(fileName, fileName, dataList, headList, tClass, basicWriteHandlerList(), response);
    }

    /**
     * easyexcel写文件操作
     * @param fileName  文件名称
     * @param dataList  数据列表
     * @param headList  数据列表
     * @param tClass    泛型类class对象
     * @param response  http响应对象
     * @param <T> 泛型类型
     */
    public static <T> void writeResponse(String fileName, List<T> dataList, List<List<String>> headList,
                                         Class<T> tClass, List<WriteHandler> writeHandlerList, HttpServletResponse response) {
        writeResponse(fileName, fileName, dataList, headList, tClass, writeHandlerList, response);
    }

    /**
     * easyexcel写文件操作
     * @param fileName  文件名称
     * @param sheetName 文件sheet名称
     * @param dataList  数据列表
     * @param headList  数据列表
     * @param tClass    泛型类class对象
     * @param response  http响应对象
     * @param <T> 泛型类型
     */
    public static <T> void writeResponse(String fileName, String sheetName, List<T> dataList, List<List<String>> headList,
                                         Class<T> tClass, List<WriteHandler> writeHandlerList, HttpServletResponse response) {

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        fileName = URLEncoder.encode(fileName + FileTypeEnum.XLSX.getSuffix(), StandardCharsets.UTF_8);
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);

        try {
            // 文件写入输出流
            writeOutputStream(sheetName, dataList, headList, tClass, writeHandlerList, response.getOutputStream());

        } catch (IOException e) {
            log.error("文件写入输出流异常。message={}", e.getMessage(), e);
            throw new CzzException();
        }
    }

    /**
     * easyexcel写文件操作
     * @param sheetName    文件sheet名称
     * @param dataList     数据列表
     * @param headList     数据列表
     * @param tClass       泛型类class对象
     * @param outputStream 输出流对象
     * @param <T> 泛型类型
     */
    public static <T> void writeOutputStream(String sheetName, List<T> dataList, List<List<String>> headList,
                                             Class<T> tClass, List<WriteHandler> writeHandlerList,
                                             OutputStream outputStream) {
        ExcelWriterBuilder builder = EasyExcel.write(outputStream, tClass)
                .autoCloseStream(Boolean.FALSE);
        if (!CollectionUtils.isEmpty(writeHandlerList)) {
            for (WriteHandler writeHandler : writeHandlerList) {
                builder = builder.registerWriteHandler(writeHandler);
            }
        }
        ExcelWriterSheetBuilder sheetBuilder = builder.sheet(sheetName);
        if (!CollectionUtils.isEmpty(headList)) {
            sheetBuilder = sheetBuilder.head(headList);
        }
        sheetBuilder.doWrite(dataList);
    }

    /**
     * easyexcel写文件操作
     * @param filePath  存储路径
     * @param fileName  文件名称
     * @param sheetName 文件sheet名称
     * @param dataList  数据列表
     * @param <T> 泛型类型
     */
    public static <T extends UploadVo> void writeFile(String filePath, String fileName, String sheetName,
                                                      List<T> dataList, Class<T> tClass) {
        writeFile(filePath, fileName, sheetName, dataList, null, tClass);
    }

    /**
     * easyexcel写文件操作
     * @param filePath  存储路径
     * @param fileName  文件名称
     * @param sheetName 文件sheet名称
     * @param dataList  数据列表
     * @param headList  文件表头列表
     * @param tClass    泛型类class对象
     * @param <T> 泛型类型
     */
    public static <T extends UploadVo> void writeFile(String filePath, String fileName, String sheetName,
                                                      List<T> dataList, List<List<String>> headList, Class<T> tClass) {
        // 写文件
        File file = new File(filePath + File.separatorChar + fileName);

        writeFile(file, sheetName, dataList, headList, tClass, basicWriteHandlerList());
    }

    /**
     * easyexcel写文件操作
     * @param file      文件对象
     * @param sheetName 文件sheet名称
     * @param dataList  数据列表
     * @param headList  文件表头列表
     * @param tClass    泛型类class对象
     * @param <T> 泛型类型
     */
    public static <T extends UploadVo> void writeFile(File file, String sheetName, List<T> dataList,
                                                      List<List<String>> headList, Class<T> tClass) {
        writeFile(file, sheetName, dataList, headList, tClass, basicWriteHandlerList());
    }

    /**
     * easyexcel写文件操作
     * @param file      文件对象
     * @param sheetName 文件sheet名称
     * @param dataList  数据列表
     * @param headList  文件表头列表
     * @param tClass    泛型类class对象
     * @param <T> 泛型类型
     */
    public static <T extends UploadVo> void writeFile(File file, String sheetName, List<T> dataList,
                                                      List<List<String>> headList, Class<T> tClass,
                                                      List<WriteHandler> writeHandlerList) {
        // 写文件
        if (!file.getParentFile().exists()) {
            boolean bool = file.getParentFile().mkdirs();
            log.info("新建文件目录完成。filePath={} bool={}", file.getParentFile().getAbsolutePath(), bool);
        }

        ExcelWriterBuilder builder = EasyExcel.write(file, tClass);
        if (!CollectionUtils.isEmpty(writeHandlerList)) {
            for (WriteHandler writeHandler : writeHandlerList) {
                builder.registerWriteHandler(writeHandler);
            }
        }
        ExcelWriterSheetBuilder sheetBuilder = builder.sheet(sheetName);
        if (!CollectionUtils.isEmpty(headList)) {
            sheetBuilder = sheetBuilder.head(headList);
        }
        sheetBuilder.doWrite(dataList);
    }

    /**
     * 获取基础导出处理配置对象列表
     * @return 列表
     */
    public static List<WriteHandler> basicWriteHandlerList() {
        List<WriteHandler> writeHandlerList = new ArrayList<>();
        writeHandlerList.add(new HorizontalCellStyleStrategy(getHeadCellStyle(), getContentWriteCellStyle()));
        writeHandlerList.add(new SimpleColumnWidthStyleStrategy(20));
        writeHandlerList.add(new SimpleRowHeightStyleStrategy((short) 20, (short) 20));
        return writeHandlerList;
    }

    /**
     * 获取导出文件表头样式配置
     */
    private static WriteCellStyle getHeadCellStyle() {
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景颜色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.AQUA.getIndex());
        // 样式填充类型
        headWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
        // 左边框颜色
        headWriteCellStyle.setLeftBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
        // 上边框颜色
        headWriteCellStyle.setTopBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
        // 右边框颜色
        headWriteCellStyle.setRightBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
        // 下边框颜色
        headWriteCellStyle.setBottomBorderColor(IndexedColors.GREY_25_PERCENT.getIndex());
        // 水平居中
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 垂直居中
        headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 自动换行
        headWriteCellStyle.setWrapped(Boolean.TRUE);

        // 表头字体配置
        WriteFont headWriteFont = new WriteFont();
        //
        headWriteFont.setBold(false);
        // 表头文字大小
        headWriteFont.setFontHeightInPoints((short) 14);
        // 表头文字名称
        headWriteFont.setFontName("微软雅黑");
        // 表头文字颜色
        headWriteFont.setColor(IndexedColors.WHITE.getIndex());
        // 设置标题行字体
        headWriteCellStyle.setWriteFont(headWriteFont);

        return headWriteCellStyle;
    }

    /**
     * 获取导出文件内容样式配置
     */
    private static WriteCellStyle getContentWriteCellStyle() {
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
//        // 水平居中
//        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 垂直居中
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 自动换行
        contentWriteCellStyle.setWrapped(Boolean.TRUE);

        // 内容字体配置
        WriteFont contentWriteFont = new WriteFont();
        // 内容字体大小
        contentWriteFont.setFontHeightInPoints((short) 12);
        // 内容字体名称
//        contentWriteFont.setFontName("微软雅黑");
        // 设置内容配置
        contentWriteCellStyle.setWriteFont(contentWriteFont);

        return contentWriteCellStyle;
    }
}
